<template>
  <div class="upCopperCont">
    <div class="formVal headImg">
      <div v-if="!headImg" class="upImg">
        <div class="upload-inner">
          <div class="iconfont icon-shangchuan1 icon-shangchuan"></div>
          <div class="upText">{{ text }}</div>
        </div>
      </div>
      <img v-if="headImg" :src="headImg" />
      <input ref="file" type="file" @change="onFileChange($event)" />
      <div v-if="headImg" class="iconfont icon-shangchuan upIcon_"></div>
    </div>
    <cool-dialog
      v-model="dialogVisible"
      title="图片裁剪"
      :closeOnClickModal="true"
      @confirm="onUpdatePhoto"
      @cancel="cancelFn"
    >
      <div class="preview-image-wrap">
        <img
          ref="preview-image"
          class="preview-image"
          :src="previewImage"
          alt=""
        />
      </div>
    </cool-dialog>
  </div>
</template>

<script>
import "cropperjs/dist/cropper.css";
import Cropper from "cropperjs";
import { uploadFile } from "@/http/upfile.js";
import { ElMessage, ElMessageBox, ElLoading } from "element-plus";
import CoolDialog from "@/components/CoolDialog.vue";

export default {
  components: { CoolDialog },
  data () {
    return {
      previewImage: "",
      dialogVisible: false,
      imgArr: [{ img: "" }],
      headImg: this.propImg,
    };
  },
  props: {
    aspectRatio: {
      default: 1 / 1,
    },
    propImg: {
      default: "",
    },
    width: {
      default: "100px",
    },
    height: {
      default: "100px",
    },
    iconSize: {
      default: "45px",
    },
    text: { default: "图片上传" },
    radio: {
      default: "12px",
    },
  },

  methods: {
    cancelFn () {
      this.dialogVisible = false;
      if (this.cropper) {
        this.cropper.destroy();
      }
      this.previewImage = "";
      this.$refs.file.value = "";
    },
    onFileChange (e) {
      let file = e.target.files[0];
      let blobData = window.URL.createObjectURL(file);
      this.previewImage = blobData;
      this.dialogVisible = true;
      // 解决选择相同图片不触发change事件的问题
      this.$refs.file.value = "";
    },
    onUpdatePhoto () {
      this.cropper.getCroppedCanvas().toBlob(async (file) => {
        const loading = ElLoading.service({
          lock: true,
          text: "Loading",
          background: "rgba(255, 255, 255, 0.7)",
        });
        try {
          let { src } = await uploadFile(file);
          if (src) {
            this.headImg = src;
            this.$emit("ok", src);
            this.previewImage = src;
            this.dialogVisible = false;
            this.cropper.destroy();
          } else {
            ElMessage({
              type: "error",
              message: "裁剪失败",
            });
          }
        } catch {
          ElMessage({
            type: "error",
            message: "服务异常",
          });
        }
        loading.close();
      });
    },

    onDialogOpened () {
      this.$nextTick(() => {
        let image = this.$refs["preview-image"];
        if (image) {
          let cropper = new Cropper(image, {
            aspectRatio: this.aspectRatio, // 裁剪框比列  1/1 长与宽的比列  NaN:任意比列
            viewMode: 1, // 0:对裁剪框的移动没有限制  1:裁剪框不能超过图片//2:裁剪框不能超过图片且图片高度和阴影背景高度一样  3:让图片完全填充阴影背景
            dragMode: "none",
            zoomOnTouch: true, //是否可以通过触摸的形式来去放大图片(手机端)
            zoomable: true, //是否允许缩放图片
            autoCropArea: 1, //当初始化时，裁剪框的大小与原图的比例
            background: true, //是否显示网格背景
            center: true, //裁剪框是否在图片的中心
            cropBoxResizable: true, //是否可以调节裁剪框的大小
          });
          this.cropper = cropper;
        }
      });
    },
  },
  watch: {
    dialogVisible (val) {
      if (val) {
        this.onDialogOpened();
      }
    },
  },
  mounted () {},
  created () {},
};
</script>

<style scoped lang="less">
.headImg {
  width: v-bind(width);
  height: v-bind(height);
  border-radius: v-bind(radio);
  cursor: pointer;
  background: linear-gradient(145deg, #f6f8fc, #e8ecf5);
  border: none;
  position: relative;
  overflow: hidden;
  transition: all 0.3s ease;
  box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.05),
    -5px -5px 10px rgba(255, 255, 255, 0.8);

  &:hover {
    box-shadow: 7px 7px 15px rgba(0, 0, 0, 0.08),
      -7px -7px 15px rgba(255, 255, 255, 0.9);
    transform: translateY(-2px);

    .upImg {
      .upload-inner {
        .iconfont {
          color: #4b58dc;
          transform: scale(1.1) rotate(10deg);
          text-shadow: 0 0 10px rgba(64, 158, 255, 0.4);
        }

        .upText {
          color: #4b58dc;
          font-weight: normal;
          font-size: 13px;
        }

        &:after {
          transform: translate(-50%, -50%) scale(1.2);
          opacity: 0.3;
        }
      }
    }
    .upIcon_ {
      opacity: 1;
    }
  }

  &:active {
    box-shadow: inset 3px 3px 6px rgba(0, 0, 0, 0.08),
      inset -3px -3px 6px rgba(255, 255, 255, 0.8);
    transform: translateY(0);
  }

  .upIcon_ {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    font-size: 30px;
    line-height: v-bind(height);
    color: #fff;
    background-color: rgba(0, 0, 0, 0.3);
    opacity: 0;
    text-align: center;
    border-radius: 10px 0px 10px 0;
    z-index: 2;
    transition: all 0.3s ease;
    &:hover {
      opacity: 1;
      transform: scale(1.05);
    }
  }

  input {
    width: 100%;
    height: 100%;
    opacity: 0;
    position: absolute;
    top: 0;
    left: 0;
    cursor: pointer;
    z-index: 10;
  }
  .upImg {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;

    .upload-inner {
      text-align: center;
      position: relative;
      .iconfont {
        font-size: 30px;
        color: #8c9cb8;
        transition: all 0.3s ease;
      }
      .upText {
        margin-top: 8px;
        color: #4b58dc;
        font-weight: normal;
        font-size: 13px;
        color: #8c9cb8;
        transition: all 0.3s ease;
      }
    }
  }
  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    border-radius: v-bind(radio);
    transition: all 0.3s ease;
  }
}

.preview-image-wrap {
  width: 100%;
  background-color: #f5f7fa;
  height: 400px;
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;

  .preview-image {
    display: block;
    max-width: 100%;
    max-height: 100%;
  }
}
</style>
